package kevin.framework.basic.service.impl;

import java.io.Serializable;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.AbstractPlatformTransactionManager;
import org.springframework.transaction.support.DefaultTransactionDefinition;

import kevin.framework.basic.common.thread.DaoDBKeyHolder;
import kevin.framework.basic.common.utils.DynamicParameter;
import kevin.framework.basic.common.utils.PagingResult;
import kevin.framework.basic.dao.IBaseDao;
import kevin.framework.basic.dao.impl.BaseDao;
import kevin.framework.basic.service.IBaseService;

/**
 * @ClassName: BaseService
 * @Description: 基本的增删改查业务类
 * @author hjwen
 * @date 2014-12-1 下午5:21:11
 * @param <T> 对应的领域实体类型
 * @param <K> 主键数据类型
 */
public abstract class BaseService<T extends Serializable, K extends Serializable> implements IBaseService<T, K> {

	/**
	 * @Fields txManager : 用于编程方式，手工控制事务 DataSourceTransactionManager
	 *         JtaTransactionManager
	 */
	protected AbstractPlatformTransactionManager txManager;

	@Resource(name = "transactionManager")
	public void setTxManager(AbstractPlatformTransactionManager txManager) {
		this.txManager = txManager;
	}

	/**
	 * 切换到指定数据库
	 ***/
	protected void setDbKey(String key) {
		DaoDBKeyHolder.setKey(key);
	}

	/**
	 * 恢复到默认数据库
	 ***/
	protected void clearDbKey() {
		DaoDBKeyHolder.clear();
	}

	protected IBaseDao<T, K> dao;

	protected IBaseDao<T, K> getDao() {
		return this.dao;
	}

	public final Logger logger = LoggerFactory.getLogger(getClass());

	/**
	 * 设置dao的抽象方法，子类必须实现，并设置好子类对应的dao,实现时，请采用spring注入
	 * 
	 * @param IBaseDao
	 */
	public abstract void setDao(IBaseDao<T, K> dao);

	@Override
	public boolean uniqueValid(Map<String, Object> params) throws Exception {
		boolean isPast = true;
		int res = getDao().count(params);
		if (res > 0) {
			isPast = false;
		}
		return isPast;
	}

	@Override
	public int insert(T entity) throws Exception {
		return getDao().insert(entity);
	}

	@Override
	public int update(T entity) throws Exception {
		return getDao().update(entity);
	}

	@Override
	public int updateParam(Map<String, Object> param) throws Exception {
		return getDao().updateParam(param);
	}

	@Override
	public int delete(K primaryKey) throws Exception {
		return getDao().delete(primaryKey);
	}

	@Override
	public int deleteList(List<K> list) throws Exception {
		for (K key : list) {
			this.delete(key);
		}
		return 0;
	}

	@Override
	public int deleteParam(Map<String, Object> param) throws Exception {
		return getDao().deleteParam(param);
	}

	@Override
	public int truncate() throws Exception {
		return getDao().truncate();
	}

	@Override
	public int countAll() throws Exception {
		return getDao().count(null);
	}

	@Override
	public int count(Map<String, Object> param) throws Exception {
		return getDao().count(param);
	}

	@Override
	public T get(K primaryKey) throws Exception {
		return getDao().get(primaryKey);
	}

	@Override
	public List<T> selectAll() throws Exception {
		return getDao().selectParam(null);
	}

	@Override
	public List<T> selectParam(Map<String, Object> param) throws Exception {
		return getDao().selectParam(param);
	}

	@Override
	public PagingResult<T> selectPagination(DynamicParameter param) throws Exception {
		return getDao().selectPagination(param);
	}

	@Override
	public void insertList(List<T> list) throws Exception {
		IBaseDao<T, K> dao = getDao();
		for (T t : list) {
			dao.insert(t);
		}
	}

	@Override
	public int insertBatch(List<T> list) throws Exception {
		return getDao().insertBatch(list);
	}

	@Override
	public int updateBatch(List<T> list) throws Exception {
		return getDao().updateBatch(list);
	}

	@Override
    public int deleteBatch(List<K> list) throws Exception {
        return getDao().deleteBatch(list);
    }

	@Override
	public Map<K, T> selectMap(Map<String, Object> param, String keyName) throws Exception {

		return getDao().selectMap(param, keyName);
	}

	@Override
	public Map<K, T> selectMap(Map<String, Object> param) throws Exception {
		return getDao().selectMap(param, "id");
	}

	@Override
	public Map<K, T> selectAllMap() throws Exception {
		return getDao().selectMap(null, "id");
	}

	@Override
	public Map<K, T> selectAllMap(String keyName) throws Exception {
		return getDao().selectMap(null, keyName);
	}

	@Override
	public int xlsBatchInsert(List<T> list, int commitNum) throws Exception {
		if (logger.isDebugEnabled()) {
			logger.debug("开始导入数据");
		}
		DefaultTransactionDefinition def = new DefaultTransactionDefinition();
		def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
		TransactionStatus status = txManager.getTransaction(def);
		int suceesful = 0;
		int i = 0;
		boolean hasCommit = false;
		try {
			for (T bean : list) {
				hasCommit = false;
				this.insert(bean);
				if (i == commitNum) {
					txManager.commit(status);
					hasCommit = true;
					if (logger.isDebugEnabled()) {
						logger.debug("第" + suceesful + "条数据  commit..........................");
					}
					i = 0;
					status = txManager.getTransaction(def);
				}
				i++;
				suceesful++;
			}
		} catch (Exception ex) {
			try {
				txManager.rollback(status);
			} catch (Exception e) {
				logger.error("{}", e);
			}
			logger.error("{}", ex);
			return suceesful;
		}
		if (!hasCommit) {
			txManager.commit(status);
		}
		if (logger.isDebugEnabled()) {
			logger.debug("导入数据结束");
		}
		return suceesful;
	}

	@Override
	public int xlsBatchUpdate(List<T> list, int commitNum) throws Exception {
		// TODO Auto-generated method stub
		return 0;
	}

	@Override
	public int insertObject(Object entity) throws Exception {

		return this.insert((T) entity);
	}

	@Override
	public int updateObject(Object entity) throws Exception {
		return this.update((T) entity);
	}

}
